Skip to content

Hotfix 24.2.1: cherry-pick onboarding telemetry (#3088, #3111, #3117), Fixes AB#3462876#3119

Merged
wzhipan merged 4 commits into
working/release/24.2.1from
zhipan/hotfix-24.2.1-onboarding-telemetry
May 16, 2026
Merged

Hotfix 24.2.1: cherry-pick onboarding telemetry (#3088, #3111, #3117), Fixes AB#3462876#3119
wzhipan merged 4 commits into
working/release/24.2.1from
zhipan/hotfix-24.2.1-onboarding-telemetry

Conversation

@wzhipan
Copy link
Copy Markdown
Contributor

@wzhipan wzhipan commented May 16, 2026

Cherry-picks the onboarding telemetry feature into the 24.2.1 hotfix release branch.

Cherry-picked from dev (in order):

PR Commit Description
#3088 543578aa4 Add onboarding telemetry recorder, field keys, and session correlation store
#3111 0965c25ca Add onboarding telemetry blob fields to BrokerRequest/BrokerResult and command parameters for client↔broker IPC transport
#3117 1fe87aaa5 Add additional step ID and blocking error constants for full onboarding telemetry coverage

All three are part of the same feature (mobile onboarding telemetry, AB#3462876 / AB#3568357) and are bundled here so OneAuth can take a single hotfix dependency.

Conflicts resolved: changelog.txt only — entries moved from vNext to Version 24.2.1-RC1. No code conflicts.

Fixes AB#3462876

wzhipan added 3 commits May 15, 2026 16:53
… store for mobile onboarding flow, Fixes AB#3462876 (#3088)

Adds shared Android infrastructure for tracking mobile onboarding
telemetry — the E2E flow where users hit Conditional Access (CA)
blocking errors (broker install, MDM enrollment, device registration)
and must remediate before completing sign-in.

Consumed by both OneAuth (non-brokered flows) and broker (brokered
flows) to construct a JSON telemetry blob emitted through MATS.

Linked Feature:
[AB#3462876](https://identitydivision.visualstudio.com/fac9d424-53d2-45c0-91b5-ef6ba7a6bf26/_workitems/edit/3462876)
Linked PBI:
[AB#3568356](https://identitydivision.visualstudio.com/fac9d424-53d2-45c0-91b5-ef6ba7a6bf26/_workitems/edit/3568356)

- JSON field key constants for the onboarding blob — all snake_case
matching MATS convention (EntityStore prepends `mo_` to produce final
MATS columns, e.g. `blocking_errors` → `mo_blocking_errors`)
- Step ID constants (`AuthenticationStarted`, `BrokerInstallPrompted`,
`DeviceRegistrationStarted`, etc.)
- Blocking error value constants (`BROKER_INSTALLATION_TRIGGERED`,
`MDM_FLOW`) — must match C++ hardcoded strings in OneAuth''s
`InteractiveRequest.cpp`

- Records steps, blocking errors, and domain tracking during interactive
auth flows
- Constructs the blob from a seed JSON provided by C++ xplat core
- `addStep(stepId)` captures the current ISO-8601 timestamp internally —
callers no longer pass a timestamp
- `finalizeBlob()` returns populated JSON only if blocking errors were
recorded AND `sessionCorrelationId` is non-empty (empty string
otherwise); logs at verbose/warn/error level for diagnostics
- Persists `sessionCorrelationId` to SharedPreferences on block
detection for app-kill resilience

- SharedPreferences-backed persistence for session correlation IDs
(per-app sandbox; same schema/file name across apps for consistency)
- Used by OneAuth''s Djinni `SessionCachePersistence` adapter (JNI
bridge to C++ `SessionCorrelationIdCache`)

- **Kotlin**: Implemented in Kotlin, consistent with recent additions to
Common (e.g. `BrowserRedirectValidator`,
`DeviceRegistrationClientApplication`). Public surface remains
JVM-compatible for Java callers.
- **Snake_case blob keys**: All internal JSON keys use snake_case
(`session_correlation_id`, `blocking_errors`, etc.) so EntityStore can
use simple `"mo_" + key` concatenation for MATS columns — no mapping
table needed, follows established MATS convention
- **Recorder, not builder**: The class records events incrementally
during WebView navigation with mid-flow side effects (SharedPreferences
persistence), so it''s named `OnboardingTelemetryRecorder` rather than
following the builder pattern
- **No `remediationNeeded` field**: Redundant — implied by the presence
of `blocking_errors`
- **`apply()` over `commit()` for persistence**: Telemetry tolerates
rare loss; blocking errors leave the app alive for seconds-to-minutes of
user remediation, so the async flush window is far longer than typical
loss. Avoids main-thread disk I/O.

- 20 Common Android/Robolectric unit tests pass (recorder + store)
- OneAuth C++ unit tests pass (794 tests, 0 failures) including 41 new
onboarding-specific tests
- E2E tested with OneAuthTestApp: CA-blocked user triggers
`BROKER_INSTALLATION_TRIGGERED`, blob emitted with correct fields and
`sessionCorrelationId`

- Renamed `OnboardingBlobFieldKeys` → `OnboardingTelemetryConstants`
- Renamed `OnboardingSessionCachePersistence` →
`OnboardingSessionCorrelationStore`
- `addStep()` now captures timestamp internally (single-arg signature)
- Added Logger calls in `finalizeBlob()` (verbose/error), seed-parse
`init` catch (warn), and `persistSessionCorrelation()` catch (warn)
- `finalizeBlob()` now early-returns with a warn log if
`sessionCorrelationId` is empty (avoids emitting uncorrelatable
telemetry)
- Replaced `java.time.Instant` with `SimpleDateFormat` (desugaring
disabled, minSdk 24)
- Extracted `FIELD_ID` constant for the cache entry key
- Clarified `OnboardingSessionCorrelationStore` Javadoc (per-app
SharedPreferences sandbox)
- Updated `addBlockingError` Javadoc to reference correct constant
values
- Full MIT license headers
- Converted to Kotlin

- **Upstream of**: OneAuth onboarding telemetry PR (Djinni + C++ core +
Android platform layer)
- **No breaking changes**: all new files, no modifications to existing
code
…3111)

Adds the IPC plumbing for the onboarding telemetry blob to flow
client↔broker. Independent of PR #3088 (which adds the
recorder/store/constants); both are needed together for end-to-end
brokered onboarding telemetry.

Linked Feature:
[AB#3462876](https://identitydivision.visualstudio.com/fac9d424-53d2-45c0-91b5-ef6ba7a6bf26/_workitems/edit/3462876)
Linked PBI:
[AB#3568357](https://identitydivision.visualstudio.com/fac9d424-53d2-45c0-91b5-ef6ba7a6bf26/_workitems/edit/3568357)

| File | Change |
|---|---|
| `BrokerRequest.java` | Add `onboarding_seed_json` field (client →
broker) |
| `BrokerResult.java` | Add `onboarding_blob` field + builder + getter
(broker → client) |
| `InteractiveTokenCommandParameters.java` | Add `onboardingSeedJson`
field on the params builder |
| `AcquireTokenResult.java` | Add `onboardingBlob` field for carrying
the populated blob through the result chain |
| `MsalBrokerRequestAdapter.java` | Serialize `onboardingSeedJson` from
command parameters into `BrokerRequest` |
| `MsalBrokerResultAdapter.java` | Extract `onboardingBlob` from
`BrokerResult` into `AcquireTokenResult` |

All additions are pure data fields + adapter wiring. No behavior change
for existing callers (fields default to empty/null when not set).

- **Direction `client → broker`**: OneAuth/MSAL builds the seed JSON
(containing `sessionCorrelationId`, `onboardingMode`, `schema_version`)
and attaches it to the interactive request. The broker reads it via the
new field on `BrokerInteractiveTokenCommandParameters`, constructs its
own `OnboardingTelemetryRecorder` from the seed, and uses the same
correlation ID for its onboarding telemetry events.
- **Direction `broker → client`**: When the broker emits the populated
onboarding blob (after `finalizeBlob()`), it places it into
`BrokerResult.onboarding_blob`. The client extracts it into
`AcquireTokenResult.onboardingBlob`, where downstream OneAuth code reads
it and emits the blob through MATS.

See full design: [Mobile Onboarding Telemetry
Design](https://identitydivision.visualstudio.com/Engineering/_workitems/edit/3462876)
§6.6 (persistence and propagation) and §11.2 (broker → OneAuth blob
delivery).

- **Pairs with**: PR #3088 (`OnboardingTelemetryRecorder` +
`OnboardingTelemetryConstants` + `OnboardingSessionCorrelationStore`).
The recorder consumes the seed JSON read out of these IPC fields.
- **Consumers**:
- OneAuth:
[`shared/mobile-onboarding-android-fixes`](https://office.visualstudio.com/OneAuth/_git/OneAuth)
updates `BrokerRequestConverter` / `BrokerResultConverter` to read/write
these fields.
- Broker (`ad-accounts-for-android`):
`MsalAndroidBrokerCommandParameterAdapter` reads `onboardingSeedJson`;
broker error handler / SSO controller will write `onboarding_blob` once
the recorder lifecycle is wired (separate PBI,
[AB#3568359](https://identitydivision.visualstudio.com/fac9d424-53d2-45c0-91b5-ef6ba7a6bf26/_workitems/edit/3568359)).
- **No breaking changes**: all new optional fields, no modifications to
existing serialization order or field semantics.

- Round-trip serialization is exercised by existing `BrokerRequest` /
`BrokerResult` tests (Gson + Bundle); new fields default to empty/null
when not set, so no existing test should regress.
- E2E validated locally via OneAuth `local-only-onboarding-telemetry`
branch + a combined Common build (`mavenLocal` `0.0.0-zhipan-mot-7`):
seed JSON flows OneAuth → BrokerRequest → broker → BrokerResult →
OneAuth.
…lemetry, Fixes AB#3462876 (#3117)

Adds the remaining step ID and blocking error constants from the Mobile
Onboarding Telemetry design (section 9 Step Taxonomy) to
`OnboardingTelemetryConstants`. Pure additive - no behavior change, no
caller wiring in this PR.

Linked Feature:
[AB#3462876](https://identitydivision.visualstudio.com/fac9d424-53d2-45c0-91b5-ef6ba7a6bf26/_workitems/edit/3462876)

PR #3088 shipped the recorder + the 5 step/blocking-error constants
OneAuth needed for non-brokered (`STEP_AUTHENTICATION_STARTED`,
`STEP_BROKER_INSTALL_PROMPTED`, `STEP_DEVICE_REGISTRATION_STARTED`,
`BLOCKING_ERROR_BROKER_INSTALL`, `BLOCKING_ERROR_MDM_FLOW`). The
remaining ~20 step IDs from the design will be needed by:

- The WebView hooks PR (follow-up) - emits `MDMEnrollmentStarted`,
`CompanyPortalLaunched`, `WebCpEnrollmentStarted`, etc. from
`AzureActiveDirectoryWebViewClient` URL-handler sites.
- Broker-side step emission (follow-up) - `AccountSelectionStarted`,
`InterruptFlowStarted`, `PrtAcquired`, `TokenIssued`, etc.
- OneAuth follow-ups for AM API + WebCP detection (Veena's request) -
needs `MDMEnrollmentStarted` constant.
- Termination steps - `UserCanceled`, `AuthorizationTimedOut`.

Landing the constants ahead of caller wiring lets downstream PRs
reference typed constants instead of hardcoded strings, and avoids a
chicken-and-egg sequencing problem.

Grouped by onboarding flow phase (matching design section 9):

- **Authentication / WebView**: `STEP_ACCOUNT_SELECTION_STARTED`,
`STEP_PASSKEY_AUTH_STARTED`, `STEP_CERT_BASED_AUTH_STARTED`
- **MFA / Strong Auth**: `STEP_STRONG_AUTH_SETUP_STARTED`,
`STEP_STRONG_AUTH_SETUP_COMPLETED`,
`STEP_AUTHENTICATOR_MFA_LINKING_STARTED`
- **CA Block & Remediation**: `STEP_CA_BLOCK_RECEIVED`,
`STEP_INTERRUPT_FLOW_STARTED`, `STEP_CONSENT_PROMPT_SHOWN`,
`STEP_TERMS_OF_USE_SHOWN`, `STEP_PASSWORD_RESET_REQUIRED`
- **Device Registration**: `STEP_DEVICE_REGISTRATION_UPGRADE_STARTED`
- **MDM Enrollment**: `STEP_MDM_ENROLLMENT_STARTED` (value
`MDMEnrollmentStarted`), `STEP_COMPANY_PORTAL_LAUNCHED`,
`STEP_WEB_CP_ENROLLMENT_STARTED`, `STEP_GOOGLE_ENROLLMENT_STARTED`
- **Intune App Protection**: `STEP_INTUNE_APP_PROTECTION_REQUIRED`
- **Compliance Remediation**: `STEP_COMPLIANCE_REMEDIATION_STARTED`,
`STEP_COMPLIANCE_REMEDIATION_COMPLETED`
- **Token Acquisition**: `STEP_PRT_ACQUIRED`, `STEP_TOKEN_ISSUED`
- **Termination**: `STEP_USER_CANCELED`, `STEP_AUTHORIZATION_TIMED_OUT`
- **Blocking error**: `BLOCKING_ERROR_DEVICE_REGISTRATION`
(`"DEVICE_REGISTRATION_REQUIRED"`)

All values are PascalCase (consistent with the existing `STEP_*`
constants and matching what eSTS/MATS expect for these enum-like step
values).

- No new tests - pure constant additions; existing
`OnboardingTelemetryRecorderTest` and
`OnboardingSessionCorrelationStoreTest` continue to pass.
- Built locally; constants compile cleanly.

- **Builds on**: PR #3088 (already merged) - extends
`OnboardingTelemetryConstants` added there.
- **Consumed by** (follow-up PRs):
- WebView page-tracking hooks (`AzureActiveDirectoryWebViewClient`
setter + emissions)
- Broker step emission (`BrokerSsoController`, `PrtController`, error
handler)
- OneAuth caller updates (AM API + WebCP detection per Veena's PR #3088
comment)
- **No breaking changes** - purely additive to the existing `object`.
@wzhipan wzhipan requested review from a team as code owners May 16, 2026 00:25
@github-actions
Copy link
Copy Markdown

✅ Work item link check complete. Description contains link AB#3462876 to an Azure Boards work item.

2 similar comments
@github-actions
Copy link
Copy Markdown

✅ Work item link check complete. Description contains link AB#3462876 to an Azure Boards work item.

@github-actions
Copy link
Copy Markdown

✅ Work item link check complete. Description contains link AB#3462876 to an Azure Boards work item.

@wzhipan wzhipan merged commit c5c0c6a into working/release/24.2.1 May 16, 2026
3 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant